/************************************
 * 
 * Copyright 2010 u6 to iAround
 * 
 * @Description:该类提供加解密操作，含有AES加密/解密，MD5、SHA-1数据签名、生成密钥种子、密钥；其中AES加密采用默认填充模式。
 * @author linyg
 * @Date:2010-07-30 11:48:38
 * @Version v1.0
 */

package com.yangguang.huahui.utils;

import java.security.KeyFactory;
import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Random;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;


public class CryptoUtil {
	// 加密算法类型
	public final static String TYPE = "AES";
	
	/** 指定加密算法为RSA */
	private static String ALGORITHM = "RSA";
	
	public final static String SZF_PUBLIC_KEY="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCPSU/43cp8Vk8Obie0zHpkN8wtAq5yK7KuT1Sq+l0zc5zmGaFuX6HK9DFvbRHkqpM8fxAekKpJQWwT/7/8lAHYoNRefZ8mMzCMBUBJcvk9iavxZVVYCFGsDETMXv4a9mpJ/4U351DVfoEndijjuBl6vYOvDNFRis3dJecvd4DhkwIDAQAB";

	/**
	 * AES加密，明文为byte字节数组
	 * 
	 * @param data data 明文
	 * @param key key 16位密钥
	 * @return byte[] 返回密文字节数组
	 */
	public static byte[] AESencode(byte[] data, String key) {
		// AES加密
		try {
			byte[] raw = key.getBytes("UTF-8");
			SecretKeySpec skeySpec = new SecretKeySpec(raw, TYPE);
			Cipher cipher = Cipher.getInstance(TYPE);
			cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
			return cipher.doFinal(data);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * AES加密，明文为String字符串,调用AESencode(byte[]data,String key)作为加密操作
	 * 
	 * @param data
	 *            data 明文字符串
	 * @param key
	 *            key 16位密钥
	 * @return String 返回16进制字符串密文
	 */
	public static String AESencode(String data, String key) {
		byte[] srcData = data.getBytes();
		byte[] endata = AESencode(srcData, key);
		return HEX.toHex(endata);
	}

	/**
	 * AES解密，密文为byte[]字节数组
	 *
	 *            data 密文字节数组
	 *            key 16位密钥
	 * @return byte[] 返回明文字节数组
	 */
	public static byte[] AESdecode(byte[] data, String kek) {
		try {
			KeyGenerator kgen = KeyGenerator.getInstance("AES");  
            kgen.init(128, new SecureRandom(kek.getBytes()));  
            SecretKey secretKey = kgen.generateKey();  
            byte[] enCodeFormat = secretKey.getEncoded();  
            SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");              
            Cipher cipher = Cipher.getInstance("AES");// 创建密码器   
            cipher.init(Cipher.DECRYPT_MODE, key);// 初始化  
//           
//			byte[] raw = key.getBytes();
//			SecretKeySpec skeySpec = new SecretKeySpec(raw, TYPE);
//			Cipher cipher = Cipher.getInstance(TYPE);
//			cipher.init(Cipher.DECRYPT_MODE, skeySpec);
			return cipher.doFinal(data);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * AES解密，密文为16进制的字符串，调用AESdecode(byte[]data,String key)作为解密操作
	 *
	 *            data 密文字符串
	 *            key 密钥
	 */
	public static String AESdecode(String data, String key) {
		byte[] endata = data.getBytes();
		byte[] dedata = AESdecode(endata, key);
		return new String(dedata);
	}

	/**
	 * 使用MD5产生消息摘要
	 *
	 *            soures 待产生消息摘要的字符串
	 * 
	 * @return 返回十六进制字符串
	 */
	public static String md5(String data) {
		if (data == null) {
			return null;
		}
		
		String s = null;
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			md.update(data.getBytes());
			byte[] tmp = md.digest();
			s = HEX.toHex(tmp);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return s;
	}

	/**
	 * 使用SHA-1产生消息摘要
	 *
	 *            待产生消息摘要的字符串
	 * 
	 * @return 返回十六进制字符串
	 */
	public static String SHA1(String data) {
		String s = null;
		try {
			MessageDigest md = MessageDigest.getInstance("SHA-1");
			md.update(data.getBytes("UTF-8"));
			byte[] tmp = md.digest();
			s = HEX.toHex(tmp);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return s;
	}
	
	/**
	 * 使用SHA-1产生消息摘要
	 * 
	 * @param data
	 *            待产生消息摘要的字符串
	 * 
	 * @return 返回十六进制字符串
	 */
	public static String SHA1_base64(String data) {
		String s = null;
		try {
			MessageDigest md = MessageDigest.getInstance("SHA-1");
			md.update(data.getBytes("UTF-8"));
			byte[] tmp = md.digest();
			s = Base64.encodeBytes(tmp);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return s;
	}
	
	/**
	 * 随机生成100-100000的整数
	 * 
	 * @return String
	 */
	public static String getRandom() {
		Random rand = new Random(System.currentTimeMillis());
		return Integer.toString(1000 + rand.nextInt(10000000));
	}
	
	
	/**
	 * 得到公钥
	 * 
	 * @param key
	 *            密钥字符串（经过base64编码）
	 * @throws Exception
	 */
	public static PublicKey getRSAPublicKey(String key) throws Exception {
		byte[] keyBytes;
		keyBytes = Base64.decode(key);

		X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		PublicKey publicKey = keyFactory.generatePublic(keySpec);
		return publicKey;
	}

	/**
	 * 得到私钥
	 * 
	 * @param key
	 *            密钥字符串（经过base64编码）
	 * @throws Exception
	 */
	public static PrivateKey getRSAPrivateKey(String key) throws Exception {
		byte[] keyBytes;
		keyBytes = Base64.decode(key);
		PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
		return privateKey;
	}

	/**
	 * 加密方法 source： 源数据
	 */
	public static String rsaEncrypt(String source,String publicKeyStr) throws Exception {
		PublicKey publicKey = getRSAPublicKey(publicKeyStr);
		/** 得到Cipher对象来实现对源数据的RSA加密 */
		Cipher cipher = Cipher.getInstance(ALGORITHM,"BC");
		cipher.init(Cipher.ENCRYPT_MODE, publicKey);
		byte[] b = source.getBytes();
		/** 执行加密操作 */
		byte[] b1 = cipher.doFinal(b);
		return Base64.encodeBytes(b1);
	}

	/**
	 * 解密算法 cryptograph:密文
	 */
	public static String rsaDecrypt(String cryptograph,String privateKeyStr) throws Exception {
		PrivateKey privateKey = getRSAPrivateKey(privateKeyStr);
		/** 得到Cipher对象对已用公钥加密的数据进行RSA解密 */
		Cipher cipher = Cipher.getInstance(ALGORITHM);
		cipher.init(Cipher.DECRYPT_MODE, privateKey);
		byte[] b1 = Base64.decode(cryptograph);
		/** 执行解密操作 */
		byte[] b = cipher.doFinal(b1);
		return new String(b);
	}
}
